﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Gunningine
{
    public class Model
    {
        private string resourceName;

        private ModelResource resource;

        private Dictionary<string, Animation> animations = new Dictionary<string, Animation>();

        private string curAnimation;

        /// <summary>
        /// Model name
        /// </summary>
        public string Name { get; private set; }

        public Animation Animation
        {
            get { return this.animations[this.curAnimation]; }
        }

        public float Size
        {
            // TODO: should use this.animations - copy info from ModelResource to Animation
            get { return this.resource.Animations[this.Animation.Name].frames[this.Animation.CurFrame].size; }
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="resource"></param>
        public Model(string resourceName)
        {
            this.resourceName = resourceName;
        }

        /// <summary>
        /// Create model: called from host code.
        /// </summary>
        /// <param name="resourceMgr"></param>
        internal void Initialise(ResourceManager resourceMgr)
        {
            this.resource = (ModelResource)resourceMgr.GetResource(resourceName);

            this.Name = this.resource.Name;

            foreach (var kvp in this.resource.Animations)
            {
                this.animations[kvp.Key] = new Animation(kvp.Key, kvp.Value.frames.Count, 6.0f);
            }

            // Set up frame events
            SetFrameEvents();

            // Set current animation to the first one.
            SetAnimation(this.animations.Keys.First());
        }

        /// <summary>
        /// Set current animation.
        /// </summary>
        /// <param name="animation"></param>
        internal void SetAnimation(string animation)
        {
            this.curAnimation = animation;
            this.Animation.Reset();
        }

        /// <summary>
        /// Update.
        /// </summary>
        /// <param name="frameTime"></param>
        internal void Update(float frameTime, Entity owner, WorldState worldState)
        {
            if (this.Animation != null)
                this.Animation.Update(frameTime, owner, worldState);
        }

        ///
        /// Accessible to scripting.
        ///

        public virtual void SetFrameEvents()
        {
        }

        /// <summary>
        /// Set frame event.
        /// </summary>
        /// <param name="animation"></param>
        /// <param name="frame"></param>
        /// <param name="handler"></param>
        protected void SetAnimationFrameEvent(string animation, int frame, Action<Entity, WorldState> handler)
        {
            this.animations[animation].SetFrameEvent(frame, handler);
        }
    }
}
